package word511;

import java.util.concurrent.*;
import java.util.concurrent.locks.*;

public class TestThread {
    private static library library = new library();
    public static void main(String[] args) {
        System.out.println("-------------------");
        System.out.println("| 图书馆借书还书流程  |");
        System.out.println("-------------------");
        //新建线程池，把还书任务和借书任务放进去
        ExecutorService executor = Executors.newFixedThreadPool(2);
        executor.execute(new returnTask());
        executor.execute(new boorroTask());

        //将线程池结束掉，释放资源
        executor.shutdown();


    }

    //新建任务类returnTask，此任务的run方法可执行静态类图书馆的还书方法，每次随机还1-5本书，运行100次
    public static class returnTask implements Runnable{
        @Override
        public void run() {
            int j = 0;
            try{
                do {
                    library.returnBook((int)(Math.random()*5)+1);  //每次随机还书1-5本
                    Thread.sleep(1000);  //每次还书休眠1秒钟再继续
                    j++;
                    //限定每天只有一百人来借书或者还书
                }
                while(j<100);
            }
            catch(InterruptedException ex){
                ex.printStackTrace(); //有线程阻塞异常时不会中断程序
            }
        }
    }

    //新建任务类boorroTask，此任务的run方法可执行静态类图书馆的借书方法，每次随机借1-5本书，运行100次
    public static class boorroTask implements Runnable{
        public void run(){
            int i=0;
            try {
                do {
                    library.borrowBooks((int)(Math.random()*5)+1);
                    Thread.sleep(1000);   //每次借完书休眠1秒钟
                   i++;
                    //限定每天只有一百人来借书或者还书
                }
                while (i<100);
            }
            catch(InterruptedException ex){
                ex.printStackTrace(); //有线程阻塞异常时不会中断程序
            }
        }
    }

    //定义静态类：图书馆类library,里面有变量margin表示书籍余量，一个借书方法，一个还书方法
    public static class library{
        private static Lock lock = new ReentrantLock();   //创建一把锁

        private static Condition newDeposit = lock.newCondition();  //创建解锁条件

        private int margin; //书籍余量

        public int getMargin() {
            return margin;
        } //获取书籍余量

        //定义borrowBooks方法，此方法用于借书
        public void borrowBooks(int num){
            lock.lock(); //先上一把锁，防止同时借书的事情发生

            try {
                while (margin < num) {       //如果书籍余量小于要借书的余量就执行下面代码
                    System.out.println();
                    System.out.println("                                                                ");
                    System.out.println("\t\t\t 什么？你想要借"+num+"本！！！");   //打印出来，表示无能为力，先睡会觉先
                    System.out.println("\t\t\t\t\t\t没有这么多书，先等一会吧~");
                    System.out.println("                                                                ");
                    System.out.println();
                    newDeposit.await();      //把当前线程阻塞掉，不借那么快了
                }
                margin -= num; //如果余量大于要借测书，就把书借出去，余量减去借书数量
                System.out.println();
                System.out.println("****************************************************************");
                System.out.println("\t\t\t 借走了"+num+"本书"+"\t\t\t 还剩下"
                +margin+"本书");
                System.out.println("****************************************************************");
                System.out.println();

                }
            catch (InterruptedException ex){
                ex.printStackTrace();    //有线程阻塞异常时不会中断程序
            }
            finally {
                lock.unlock();  //无论有没有借书成功，都把锁打开
            }
        }

        //定义returnBook方法，此方法用于还书
        public void returnBook(int num){
            lock.lock();   //还书前先上锁
            try {
                margin += num; //书籍余量加上还书数量
                System.out.println();
                System.out.println("----------------------------------------------------------------");
                System.out.println("还书成功，数量为："+num+"\t\t\t 当前书籍余量为："
                +margin);
                System.out.println("----------------------------------------------------------------");
                System.out.println();
                newDeposit.signalAll();   //叫醒所有睡觉的借书进程，我还了几本书，你们可以借书了没，不够就继续碎觉吧
            }
            finally {
                lock.unlock();   //无论结果如何，开锁
            }
        }
    }
}
